import pandas as pd
import os
from datetime import datetime, timedelta

def load_data(folder_dir, sep):
    if len(sep) > 1:
        sep = ''.join(['\\' + s for s in sep])
    lst = [a for a in os.listdir(folder_dir) if a.endswith(".csv")]
    df_list = []
    for i in lst:
        df_temp = pd.read_csv(os.path.join(folder_dir, i), sep=sep, encoding='utf8')
        df_list.append(df_temp)
    df = pd.concat(df_list, axis=0)
    return df

def load_business_change_data():
    """读取工商变更文件并处理"""
    # 使用load_data函数读取文件
    folder_dir = 'DNNFraud/dataIn/2025-2-28'
    sep = '\x7f\x5e'
    df = load_data(folder_dir, sep)
    
    # 检查并重命名相关字段
    column_mapping = {
        '主申请人统一社会信用代码': 'CREDIT_CODE',
        '申请编号': 'APPLY_NO',
        '申请日期': 'APPLY_DATE',
        '变更日期': 'ALTDATE',
        '变更事项': 'ALTITEM',
        '登记日期': 'ESDATE'
    }
    
    # 重命名列名
    df.rename(columns=column_mapping, inplace=True)
    
    # 转换日期列
    df['ESDATE'] = pd.to_datetime(df['ESDATE'])
    df['ALTDATE'] = pd.to_datetime(df['ALTDATE'])
    df['APPLY_DATE'] = pd.to_datetime(df['APPLY_DATE'])
    
    # 获取20241231的近2年的日期范围
    # latest_date = pd.to_datetime('2024-12-31')
    two_years_ago = df['APPLY_DATE'] - timedelta(days=365*2)
    
    # 筛选近2年数据
    df_recent = df[(df['ESDATE'] >= two_years_ago) &  (df['ESDATE'] <= (df['APPLY_DATE']))]
    
    # 打印统计信息
    print(f"\n=== 工商变更分析结果 ===")
    print(f"处理前总记录数: {len(df)}")
    print(f"近2年记录数: {len(df_recent)}")
    return df_recent
    
if __name__ == "__main__":
    filtered_df = load_business_change_data()

# 关联工商变更大类信息
print(f"筛选后的数据记录数: {len(filtered_df)}")
print("筛选后的数据字段:", filtered_df.columns.tolist())

# 检查filtered_df是否有数据
if len(filtered_df) == 0:
    print("警告: 筛选后的数据为空，无法进行后续处理")
    df_filtered_bs = pd.DataFrame()  # 创建空DataFrame作为结果
else:
    # 检查ALTBE和ALTAF列是否存在，如果不存在则添加
    if 'ALTBE' not in filtered_df.columns:
        print("警告: ALTBE列不存在，添加空列")
        filtered_df['ALTBE'] = ''
    if 'ALTAF' not in filtered_df.columns:
        print("警告: ALTAF列不存在，添加空列")
        filtered_df['ALTAF'] = ''
    
    # 读取变更分类的Excel文件
    try:
        df_s = pd.read_excel('DNNFraud/dataIn/韩博华工商变更重大变更数据时点24年12月31日/工商变更细分.xlsx')
        print(f"变更分类表行数: {df_s.shape[0]}")
    except Exception as e:
        print(f"读取变更分类Excel文件出错: {e}")
        print("创建空的变更分类DataFrame")
        df_s = pd.DataFrame({'变更事项': [], '变更大类': []})
    
    # 关联工商变更大类信息
    df = pd.merge(filtered_df, df_s, how='left', left_on='ALTITEM', right_on='变更事项')
    
    # 对于没有映射到的变更事项，如果ALTITEM不为空，则归类为"其他事项变更"
    df['变更大类'] = df.apply(lambda x: '其他事项变更' if (pd.notna(x['ALTITEM']) and x['ALTITEM'] != '') and pd.isna(x['变更大类']) else x['变更大类'], axis=1)
    
    # 切分数据为三种情况前，先检查各字段是否有数据
    print(f"ALTITEM非空记录数: {df['ALTITEM'].notna().sum()}")
    print(f"ALTBE非空记录数: {df['ALTBE'].notna().sum()}")
    print(f"ALTAF非空记录数: {df['ALTAF'].notna().sum()}")
    
    # 切分数据为三种情况
    # 情况1: ALTITEM为空但ALTBE不为空的记录
    df_mx1 = df[(df['ALTITEM'].isna() | (df['ALTITEM'] == '')) & (df['ALTBE'].notna() & (df['ALTBE'] != ''))].reset_index(drop=True)
    # 情况2: ALTITEM为空，ALTBE为空，但ALTAF不为空的记录 
    df_mx2 = df[(df['ALTITEM'].isna() | (df['ALTITEM'] == '')) & (df['ALTBE'].isna() | (df['ALTBE'] == '')) & (df['ALTAF'].notna() & (df['ALTAF'] != ''))].reset_index(drop=True)
    # 情况3: 不属于上述两种情况的记录
    df_mx3 = df[~(((df['ALTITEM'].isna() | (df['ALTITEM'] == '')) & (df['ALTBE'].notna() & (df['ALTBE'] != ''))) | 
                ((df['ALTITEM'].isna() | (df['ALTITEM'] == '')) & (df['ALTBE'].isna() | (df['ALTBE'] == '')) & (df['ALTAF'].notna() & (df['ALTAF'] != ''))))].reset_index(drop=True)
    
    print(f"情况1(ALTITEM为空但ALTBE不为空)记录数: {len(df_mx1)}")
    print(f"情况2(ALTITEM为空,ALTBE为空,ALTAF不为空)记录数: {len(df_mx2)}")
    print(f"情况3(其他情况)记录数: {len(df_mx3)}")
    
    # 安全地应用变更大类逻辑
    # 情况1处理
    if len(df_mx1) > 0:
        def categorize_mx1(row):
            if not isinstance(row['ALTBE'], str):
                return '其他事项变更'
            if '财务负责人' in row['ALTBE']:
                return '财务负责人'
            elif any(kw in row['ALTBE'] for kw in ['法定代表人', '经营者', '负责人']):
                return '法定代表人变更'
            elif any(kw in row['ALTBE'] for kw in ['投资人', '股东', '投资者', '出资成员', '主要成员']):
                return '投资人变更'
            elif any(kw in row['ALTBE'] for kw in ['管理人员', '监事', '经理', '董事']):
                return '高级管理人员变更'
            elif '出资' in row['ALTBE']:
                return '出资额变更'
            elif '注册资本' in row['ALTBE']:
                return '注册资本变更'
            elif any(kw in row['ALTBE'] for kw in ['范围', '项目', '业务']):
                return '经营范围变更'
            elif '期限' in row['ALTBE']:
                return '经营期限变更'
            elif '名称' in row['ALTBE']:
                return '名称变更'
            elif any(kw in row['ALTBE'] for kw in ['地址', '场所']):
                return '地址变更'
            elif any(kw in row['ALTBE'] for kw in ['行业', '门类']):
                return '行业代码变更'
            elif any(kw in row['ALTBE'] for kw in ['类型', '组成形式']):
                return '企业类型变更'
            elif any(kw in row['ALTBE'] for kw in ['管辖', '登记']):
                return '管辖机关变更'
            else:
                return '其他事项变更'
                
        df_mx1['变更大类'] = df_mx1.apply(categorize_mx1, axis=1)
    
    # 情况2处理
    if len(df_mx2) > 0:
        def categorize_mx2(row):
            if not isinstance(row['ALTAF'], str):
                return '其他事项变更'
            if '财务负责人' in row['ALTAF']:
                return '财务负责人'
            elif any(kw in row['ALTAF'] for kw in ['法定代表人', '经营者', '负责人']):
                return '法定代表人变更'
            elif any(kw in row['ALTAF'] for kw in ['投资人', '股东', '投资者', '出资成员', '主要成员']):
                return '投资人变更'
            elif any(kw in row['ALTAF'] for kw in ['管理人员', '监事', '经理', '董事']):
                return '高级管理人员变更'
            elif '出资' in row['ALTAF']:
                return '出资额变更'
            elif '注册资本' in row['ALTAF']:
                return '注册资本变更'
            elif any(kw in row['ALTAF'] for kw in ['范围', '项目', '业务']):
                return '经营范围变更'
            elif '期限' in row['ALTAF']:
                return '经营期限变更'
            elif '名称' in row['ALTAF']:
                return '名称变更'
            elif any(kw in row['ALTAF'] for kw in ['地址', '场所']):
                return '地址变更'
            elif any(kw in row['ALTAF'] for kw in ['行业', '门类']):
                return '行业代码变更'
            elif any(kw in row['ALTAF'] for kw in ['类型', '组成形式']):
                return '企业类型变更'
            elif any(kw in row['ALTAF'] for kw in ['管辖', '登记']):
                return '管辖机关变更'
            else:
                return '其他事项变更'
                
        df_mx2['变更大类'] = df_mx2.apply(categorize_mx2, axis=1)
    
    # 合并处理后的三部分数据
    df_parts = []
    if len(df_mx1) > 0:
        df_parts.append(df_mx1)
    if len(df_mx2) > 0:
        df_parts.append(df_mx2)
    if len(df_mx3) > 0:
        df_parts.append(df_mx3)
    
    if df_parts:
        df = pd.concat(df_parts, axis=0).reset_index(drop=True)
        
        # 处理变更大类为空的记录，将其标记为"无变更事项"
        df['变更大类'] = df.apply(lambda x: '无变更事项' if pd.isna(x['变更大类']) else x['变更大类'], axis=1)
        
        # 为所有记录添加result_tr列，值为1，表示该记录存在
        df['result_tr'] = 1
        
        # 使用透视表将数据从长表转为宽表
        try:
            # 首先创建APPLY_NO和CREDIT_CODE的映射
            credit_map = df[['APPLY_NO', 'CREDIT_CODE']].drop_duplicates()
            
            # 仅使用APPLY_NO作为索引创建透视表
            df_p = pd.pivot_table(df, index=['APPLY_NO'], 
                                columns='变更大类', 
                                values='result_tr', 
                                aggfunc='sum').reset_index()
            
            # 将CREDIT_CODE字段添加到透视表
            df_p = pd.merge(df_p, credit_map, how='left', on='APPLY_NO')
            
            # 调整列的顺序，将CREDIT_CODE放在APPLY_NO后面
            cols = df_p.columns.tolist()
            apply_pos = cols.index('APPLY_NO')
            cols.remove('CREDIT_CODE')
            cols.insert(apply_pos + 1, 'CREDIT_CODE')
            df_p = df_p[cols]
            
            # 后续处理保持不变
            # 定义所有可能的变更大类
            change_categories = [
                '企业类型变更', '其他事项变更', '出资额变更', '名称变更', '地址变更', '投资人变更',
                '无变更事项', '法定代表人变更', '注册资本变更', '管辖机关变更', '经营期限变更', 
                '经营范围变更', '行业代码变更', '财务负责人', '高级管理人员变更'
            ]
            
            # 处理透视表中的空值，将NaN替换为0，表示该申请号没有该类型的变更
            for category in change_categories:
                if category in df_p.columns:
                    df_p[category] = df_p[category].fillna(0)
                    # 将大于0的值设为1，表示有变更
                    df_p[category] = df_p[category].apply(lambda x: 1 if x > 0 else 0)
                else:
                    # 如果某个类别在数据中不存在，添加全0列
                    df_p[category] = 0
            
            # 计算每个申请的变更大类总次数
            df_p['变更大类次数'] = 0
            for category in change_categories:
                if category != '无变更事项':  # 排除"无变更事项"
                    df_p['变更大类次数'] += df_p[category]
            
            print(f"处理后宽表行数: {df_p.shape[0]}")
            print(f"处理后宽表列数: {df_p.shape[1]}")
            
            # 打印变更大类次数的分布
            print("\n变更大类次数分布:")
            print(df_p['变更大类次数'].value_counts().sort_index())
            
            # 将处理后的宽表保存到结果变量
            df_filtered_bs = df_p
            
            # 保存结果
            df_filtered_bs.to_csv('DNNFraud/dataOut/business_changes_wide.csv', index=False)
            print("\n宽表结果已保存至: DNNFraud/dataOut/business_changes_wide.csv")
            
        except Exception as e:
            print(f"创建宽表时出错: {e}")
            df_filtered_bs = pd.DataFrame()
    else:
        print("警告: 所有分段数据为空，无法创建宽表")
        df_filtered_bs = pd.DataFrame()

# 定义重大变更事项列表
major_changes = [
    '企业类型变更',
    '出资额变更',
    '投资人变更',
    '法定代表人变更',
    '高级管理人员变更'
]

# 筛选出符合重大变更条件的企业并统计命中次数
results = {}  # 使用字典来存储每个企业的命中次数
hit_apply_nos = set()  # 使用集合来存储命中的申请件编号

for index, row in df_filtered_bs.iterrows():
    # 检查该行是否有任何重大变更
    has_major_change = False
    hit_count = 0
    
    # 检查每个重大变更类型
    for change in major_changes:
        if change in df_filtered_bs.columns and row[change] == 1:
            has_major_change = True
            hit_count += 1
    
    # 如果有重大变更，记录该企业的命中次数和申请件编号
    if has_major_change:
        credit_code = row['CREDIT_CODE']
        if credit_code not in results:
            results[credit_code] = hit_count
        else:
            results[credit_code] = max(results[credit_code], hit_count)
        hit_apply_nos.add(row['APPLY_NO'])

# 打印统计信息
print("\n=== 重大变更统计信息 ===")
print(f"符合重大变更条件的企业总数: {len(results)}")
print(f"涉及的申请件总数: {len(hit_apply_nos)}")

# 统计命中次数分布
hit_counts = pd.Series(results.values()).value_counts().sort_index()
print("\n企业命中重大变更次数分布:")
for count, num in hit_counts.items():
    print(f"命中{count}次的企业数: {num}")

# 计算平均命中次数
avg_hits = sum(results.values()) / len(results) if results else 0
print(f"\n平均命中次数: {avg_hits:.2f}")

# 保存结果
output_path = 'DNNFraud/dataOut/filtered_business_changes.csv'
df_filtered_bs.to_csv(output_path, index=False, sep='^')
print(f"\n结果已保存至: {output_path}")

# 创建一个包含所需字段的DataFrame
overdue_info = filtered_df[['APPLY_NO', 'CREDIT_CODE', '逾期额', '不良额', '当前逾期天数']].copy()

# 筛选出命中重大变更的申请
hit_records = overdue_info[overdue_info['APPLY_NO'].isin(hit_apply_nos)]

# 打印任意逾期指标不为0的记录
print("\n=== 命中重大变更且有逾期的申请件 ===")
overdue_records = hit_records[
    (hit_records['逾期额'] > 0) | 
    (hit_records['不良额'] > 0) | 
    (hit_records['当前逾期天数'] > 0)
]
print("\n任意逾期指标不为0的记录数:", len(overdue_records))
print("\n详细记录:")
print(overdue_records.to_string(index=False))

# 打印不良额>0或当前逾期天数>30的记录
print("\n=== 命中重大变更且严重逾期的申请件 ===")
serious_overdue = hit_records[
    (hit_records['不良额'] > 0) | 
    (hit_records['当前逾期天数'] > 30)
]
print("\n不良额>0或当前逾期天数>30的记录数:", len(serious_overdue))
print("\n详细记录:")
print(serious_overdue.to_string(index=False))

# 保存结果到CSV文件
overdue_records.to_csv('DNNFraud/dataOut/hit_overdue_info.csv', index=False, sep='^')
print("\n逾期信息已保存至: DNNFraud/dataOut/hit_overdue_info.csv")

# 计算一些统计指标
print("\n=== 逾期统计指标 ===")
print(f"命中重大变更的申请件中:")
print(f"有逾期记录的比例: {len(overdue_records)/len(hit_records)*100:.2f}%")
print(f"严重逾期的比例: {len(serious_overdue)/len(hit_records)*100:.2f}%")
print("\n平均逾期指标:")
print(f"平均逾期额: {overdue_records['逾期额'].mean():.2f}")
print(f"平均不良额: {overdue_records['不良额'].mean():.2f}")
print(f"平均当前逾期天数: {overdue_records['当前逾期天数'].mean():.2f}")
